#include "config2.h"
#include "lfs/lfs_config.h"
#include "log/log2.h"

// 定义密钥文件名
#define FILE_NAME_KEY  "key"      //密钥文件名

// 声明密钥文件名的常量字符串
static const char key_file_name[] = FILE_NAME_KEY;

// 声明更新标志，用于跟踪配置是否已更新
static uint8_t config_update_flag = 0;

// 定义存储密钥的结构体
typedef struct {    
    key_t manufacturer[2];  // 制造商密钥
    key_t customer[2];      // 客户密钥
    key_t user[2];          // 用户密钥
    key_t apple[2];         // 苹果密钥
    key_t google;           // 谷歌密钥
}key_store_t;

// 声明密钥存储的全局变量
static key_store_t key_store;

// 默认密钥
static const key_t factory_keys[3] = {
    [0] = {
      .id = KID_KFR0,       // 密钥ID
      .ver = 0x01,          // 密钥版本
      .type = KEY_T_3DES,   // 密钥类型
      .data = {
        0xD2,0x22,0x9A,0xC0,0xF6,0x9F,0xC8,0x4E,
        0x87,0x4F,0x2F,0x88,0xD5,0x52,0x5B,0xA6
        },
    },

    [1] = {
        .id = KID_KFR,       // 密钥ID
        .ver = 0x01,          // 密钥版本
        .type = KEY_T_3DES,   // 密钥类型
        .data = {
            0xBF,0x84,0xB0,0xCC,0x39,0xD6,0xE1,0x53,
            0xE6,0x76,0x06,0xAF,0x46,0x5C,0x66,0x81
        },
    },

    [2] = {
       .id = KID_KFM,       // 密钥ID
       .ver = 0x01,          // 密钥版本
       .type = KEY_T_3DES,   // 密钥类型
       .data = {
            0x35,0x55,0x98,0x72,0x35,0xAA,0x4D,0xFB,
            0xF4,0xD8,0x35,0xC0,0x45,0xDF,0xDB,0x98
        }, 
   }    
};
//获取默认密钥
static const key_t* key_factory_get(uint8_t id){
    // 根据传入的id值，返回对应的默认密钥
    switch (id)
    {
    case KID_KFR0:  return &factory_keys[0]; // 返回KID_KFR0对应的默认密钥
    case KID_KFR:   return &factory_keys[1]; // 返回KID_KFR对应的默认密钥
    case KID_KFM:   return &factory_keys[2]; // 返回KID_KFM对应的默认密钥
    default:
        break;
    }
    return NULL; // 如果id不匹配任何默认密钥，返回NULL
}
//获取密钥
static key_t* config_key_get(uint8_t id){
    // 根据传入的id值，返回对应的密钥存储位置
    switch (id)
    {
    // case KID_KFR0:  return &key_default[0];
    // case KID_KFR:   return &key_default[1];
    // case KID_KFM:   return &key_default[2];

    case KID_KMR:   return &key_store.manufacturer[0]; // 返回KID_KMR对应的制造商密钥
    case KID_KMM:   return &key_store.manufacturer[1]; // 返回KID_KMM对应的制造商密钥
    
    case KID_KCR:   return &key_store.customer[0]; // 返回KID_KCR对应的客户密钥
    case KID_KCM:   return &key_store.customer[1]; // 返回KID_KCM对应的客户密钥

    case KID_KUR:   return &key_store.user[0]; // 返回KID_KUR对应的用户密钥
    case KID_KUM:   return &key_store.user[1]; // 返回KID_KUM对应的用户密钥

    case KID_APPLE_PRIV:    return &key_store.apple[0]; // 返回KID_APPLE_PRIV对应的苹果密钥
    case KID_APPLE_CRED:    return &key_store.apple[1]; // 返回KID_APPLE_CRED对应的苹果密钥

    case KID_GOOGLE:     return &key_store.google; // 返回KID_GOOGLE对应的谷歌密钥
    
    default:
        break;
    }
    return NULL;
}

static int config_read(const char* file_name, void* data, uint16_t len){
    lfs_file_t file;
    int err; 
    // 打开文件，以只读模式
    err = lfs_file_open(&lfs, &file, file_name, LFS_O_RDONLY);
    if(err){
        // 如果打开文件失败，记录错误日志并返回错误码
        LOG2_ERR("lfs_file_open error: %d", err);
        return err;
    }
    // 从文件中读取数据
    err = lfs_file_read(&lfs, &file, data, len);
    // 关闭文件
    lfs_file_close(&lfs, &file);
    if(err!= len){
        // 如果读取的数据长度不等于预期长度，记录错误日志并返回错误码
        LOG2_ERR("lfs_file_read error: %d", err);
        return -1; 
    }
    else{
        return 0; 
    }
}

static int config_write(const char* file_name, void* data, uint16_t len){
    lfs_file_t file;
    int err;
    
    // 打开文件，以读写模式，如果文件不存在则创建
    err = lfs_file_open(&lfs, &file, file_name, LFS_O_RDWR | LFS_O_CREAT);
    if(err){
        // 如果打开文件失败，记录错误日志并返回错误码
        LOG2_ERR("lfs_file_open error: %d", err);
        return -1;
    }
    // 将数据写入文件
    err = lfs_file_write(&lfs, &file, data, len);
    // 关闭文件
    lfs_file_close(&lfs, &file);
    if(err != len){
        // 如果写入的数据长度不等于预期长度，记录错误日志并返回错误码
        LOG2_ERR("lfs_file_write error: %d", err);
        return -2; 
    }
    else{
        return 0; 
    }
}

int config_init(void){
    LOG2_DBG("cfg init!");
    
    // mount the filesystem
    int err = lfs_setup();
    if(err){
        LOG2_ERR("lfs_setup error: %d", err);
        return err;
    }

    //读取配置文件
    err = config_read(key_file_name, &key_store, sizeof(key_store_t));
    return 0;
}
// 获取密钥
int config_get_key(uint8_t id, key_t* key){
    const key_t* k;
    
    // 如果id大于KID_KFM，从密钥存储中获取密钥
    if(id > KID_KFM){
        k = config_key_get(id);
    }
    // 否则，从默认密钥中获取密钥
    else{
        k = key_factory_get(id);
    }
    
    // 如果获取的密钥为NULL，记录错误日志并返回错误码
    if(k == NULL){
        LOG2_ERR("key id error: %d", id);
        return -1;
    }
    // 如果密钥类型为KEY_T_NONE，记录错误日志并返回错误码
    if(k->type == KEY_T_NONE){
        LOG2_ERR("key id: %d, type: %d", k->id, k->type);
        return -2;
    }
    // 将获取的密钥复制到传入的key指针指向的内存中
    memcpy(key, k, sizeof(key_t));
    return 0;
}

//设置密钥
int config_set_key(uint8_t id, const key_t* key) {
    // 获取指定ID的密钥存储位置
    key_t* k = config_key_get(id);
    // 如果获取失败，记录错误日志并返回错误码
    if (k == NULL) {
        LOG2_ERR("key id error: %d", id);
        return -1;
    }
    // 检测密钥是否更新
    if (memcmp(k, key, sizeof(key_t)) == 0) {
        // 如果密钥未更新，直接返回
        return 0; 
    }
    // 更新密钥
    memcpy(k, key, sizeof(key_t));
    // 设置更新标志
    config_update_flag = 1;
    return 0;
}

// 保存配置
int config_sync(void) {
    // 如果没有更新，直接返回
    if (config_update_flag == 0) {
        return 0;
    }
     // 清除更新标志
     config_update_flag = 0;
     
     int err = 0;
    // 将密钥存储写入文件
    err = config_write(key_file_name, &key_store, sizeof(key_store_t));
    // 如果写入失败，记录错误日志并返回错误码
    if (err) {
        LOG2_ERR("config_write error: %d", err);
        return err;
    }

    return 0;
}

int config_update(const key_t* key, uint8_t num){
    for(uint8_t i = 0; i < num; i++){
        config_set_key(key[i].id, &key[i]);
    }
    return 0;
}
// int config_update(const key_t* key, uint8_t num){
//     for(uint8_t i = 0; i < num; i++){
//         int ret = config_set_key(key[i].id, &key[i]);
//         if(ret != 0){
//             if(update_flag){
//                 // 恢复配置
//                 update_flag = 0;
//                 ret = config_read(key_file_name, &key_store, sizeof(key_store_t));
//                 if(ret!= 0){
//                    memset(&key_store, 0, sizeof(key_store_t));
//                 }
//             }
//             return ret;
//         }
//     }
//     return 0;
// }